<?php
/**
 * Created by PhpStorm.
 * User: Mr.Li <lhb2002@qq.com>
 * Date: 2020/1/10
 * Time: 14:00
 */

namespace LHB\ApiEarlyWarning;


/**
 * 数量统计
 * Class Summary
 * @package LHB\ApiEarlyWarning
 * User: Mr.Li <lhb2002@qq.com>
 * Date: 2020/1/10
 * Time: 14:00
 */
class Summary
{
    const KEY_SUMMARY_PREFIX = 'summary:';


    const KEY_FIELD_SUCCESS = 'success';
    const KEY_FIELD_FAILURE = 'failure';
    const KEY_FIELD_ERROR = 'error';
    const KEY_FIELD_EXECUTE = 'execute';


    private $redis ;
    private $service;
    private $expire;

    /**
     * 快速实例化对象
     * @param \Redis $redis
     * @param string $service
     * @param string $expire
     * @return Summary
     * User: Mr.Li <lhb2002@qq.com>
     * Date: 2020/1/10
     * Time: 14:26
     */
    public static function make(
        \Redis $redis ,
        string $service ,
        string $expire = '+1 day 01:20:00'
    )
    {
        $obj = new static( $redis , $service ,$expire );
        return $obj;
    }

    public function __construct(
        \Redis $redis ,
        string $service ,
        string $expire = '+1 day 01:20:00'
    )
    {
        $this->redis = $redis;
        $this->service = $service;
        $this->expire = $expire;
    }

    /**
     * 获取服务键名
     * @return string
     * User: Mr.Li <lhb2002@qq.com>
     * Date: 2020/1/9
     * Time: 14:37
     */
    private function key( )
    {
        return self::KEY_SUMMARY_PREFIX . $this->service ;
    }

    /**
     * 获取统计数据的key
     * @param string $day
     * @return string
     * User: Mr.Li <lhb2002@qq.com>
     * Date: 2020/1/10
     * Time: 13:30
     */
    private function summaryKey( $day = 'now' ){
        $day = date('Ymd' , strtotime( $day ) );
        return $this->key() . $day;
    }

    /**
     * 记录统计数据
     * @param $tag
     * @throws \Exception
     * User: Mr.Li <lhb2002@qq.com>
     * Date: 2020/1/10
     * Time: 14:16
     */
    private function recordSummary( $tag ){

        $this->redis->hIncrBy( $this->summaryKey(), $tag ,1);
        $ttl = $this->redis->ttl( $this->summaryKey() );
        if ( -1 === $ttl )
        {
            //设置统计过期时间为次日01:20:00前后100秒
            $expire = strtotime( $this->expire ) + random_int( -100 ,100 );
            $this->redis->expireAt( $this->summaryKey() , $expire );
        }
    }

    /**
     * 记录成功数据
     * @throws \Exception
     * User: Mr.Li <lhb2002@qq.com>
     * Date: 2020/1/10
     * Time: 14:16
     */
    public function success()
    {
        $this->recordSummary( self::KEY_FIELD_SUCCESS );
    }

    /**
     * 记录失败数据
     * @throws \Exception
     * User: Mr.Li <lhb2002@qq.com>
     * Date: 2020/1/10
     * Time: 14:16
     */
    public function failure()
    {
        $this->recordSummary( self::KEY_FIELD_FAILURE );
    }

    /**
     * 记录异常（错误）数据
     * @throws \Exception
     * User: Mr.Li <lhb2002@qq.com>
     * Date: 2020/1/10
     * Time: 14:16
     */
    public function error()
    {
        $this->recordSummary( self::KEY_FIELD_ERROR );
    }

    /**
     * 记录请求（执行）数据
     * @throws \Exception
     * User: Mr.Li <lhb2002@qq.com>
     * Date: 2020/1/10
     * Time: 14:16
     */
    public function execute()
    {
        $this->recordSummary( self::KEY_FIELD_EXECUTE );
    }

    /**
     * 获取指定日期的统计数据
     * @param string $day
     * @param array $fields
     * @return array|string
     * User: Mr.Li <lhb2002@qq.com>
     * Date: 2020/1/10
     * Time: 14:16
     */
    public function getSummary( $day = 'now' , $fields = [] )
    {
        $key = $this->summaryKey( $day );
        if( empty( $fields ) )
        {
            return $this->redis->hGetAll( $key );
        }
        elseif ( is_array( $fields ) )
        {
            return $this->redis->hMGet( $key , $fields );
        }
        elseif ( is_string( $fields ) )
        {
            return $this->redis->hGet( $key , $fields );
        }
    }

    /**
     * 获取昨天的统计数据，需要在过期时间前进行执行
     * @param array $fields
     * @return array|string
     * User: Mr.Li <lhb2002@qq.com>
     * Date: 2020/1/10
     * Time: 14:16
     */
    public function getYesterdaySummary( $fields = [] )
    {
        return $this->getSummary( 'yesterday' , $fields );
    }

    /**
     * 获取今天的统计数据
     * @param array $fields
     * @return array|string
     * User: Mr.Li <lhb2002@qq.com>
     * Date: 2020/1/10
     * Time: 17:31
     */
    public function getToDaySummary( $fields = [] )
    {
        return $this->getSummary( 'now' , $fields );
    }

    /**
     * 移除特定时间的数据
     * @param string $day
     * User: Mr.Li <lhb2002@qq.com>
     * Date: 2020/1/10
     * Time: 17:31
     */
    public function remove($day = 'now' )
    {
        $this->redis->del([
            $this->summaryKey( $day )
        ]);
    }

    /**
     * 移除当天的数据
     * User: Mr.Li <lhb2002@qq.com>
     * Date: 2020/1/10
     * Time: 17:33
     */
    public function removeToDay()
    {
        $this->remove('now' );
    }

    /**
     * 移除昨天的数据
     * User: Mr.Li <lhb2002@qq.com>
     * Date: 2020/1/10
     * Time: 17:33
     */
    public function removeYesterday()
    {
        $this->remove('yesterday' );
    }
}